package cn.iocoder.boot.service.impl.supplier;

import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.boot.dto.OrderTo;
import cn.iocoder.boot.dto.SKU;
import cn.iocoder.boot.entity.ComponentPrice;
import cn.iocoder.boot.entity.ComponentStock;
import cn.iocoder.boot.enums.SupplierCodeEnum;
import cn.iocoder.boot.service.CallLimitService;
import cn.iocoder.boot.service.ComponentPriceService;
import cn.iocoder.boot.service.ComponentStockService;
import cn.iocoder.boot.service.impl.SalePriceConfigServiceImpl;
import cn.iocoder.boot.utils.Base64Util;
import cn.iocoder.boot.utils.MD5Util;
import cn.iocoder.boot.utils.MessageUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import com.baomidou.dynamic.datasource.annotation.DS;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

import static cn.iocoder.boot.enums.SupplierCodeEnum.JBCHIP;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;

/**
 * 京北通宇（JBCHIP）供应商服务实现类
 * 功能：库存查询、价格查询、订单创建、初始化数据同步
 */
@Service
@DS("master")
@Slf4j
public class JBCHIPServiceImpl {

    // 常量定义：API固定参数（集中管理，便于维护）
    private static final String API_URL = "https://www.jbchip.com/gateway.action";
    private static final String PARTNER_ID = "jbchip";
    private static final String APP_ID = "ty885950";
    private static final String VERSION = "1.0";
    private static final String SIGN_TYPE = "MD5";
    private static final String CHARSET = "utf-8";
    private static final String FORMAT = "JSON";
    private static final String API_KEY = "S0BpdFwqaUYh0oHsxBb2NI";
    private static final int TIMEOUT = 30000; // 超时时间（毫秒）
    private static final int DEFAULT_STOCK_TYPE = 1; // 默认库存类型
    private static final int EXPRESS_ID = 26; // 默认物流ID
    private static final int IS_DIRECT = 0; // 直邮标识（0：非直邮）

    // 服务依赖注入
    @Resource
    private ComponentStockService componentStockService;
    @Resource
    private ComponentPriceService componentPriceService;
    @Resource
    private CallLimitService callLimitService;
    @Resource
    private SalePriceConfigServiceImpl salePriceConfigService;

    /**
     * 批量询价接口（根据型号列表查询价格并同步到数据库）
     *
     * @param models               型号列表
     * @param componentSupplierMap 供应商系数映射（key：供应商编码，value：系数）
     * @return 操作结果
     */
    @PermitAll
    public void query(List<String> models, Map<String, BigDecimal> componentSupplierMap) {
        for (String model : models) {
            try {
                queryOne(model, componentSupplierMap);
            } catch (Exception e) {
                log.error("批量查询组件信息失败，型号: {}", model, e);
                MessageUtil.sentMessage("26827", "京北通宇查询型号价格异常" + e.getMessage(), "艾矽易查询型号价格异常");
            }
        }
    }

    /**
     * 单个型号查询（同步库存信息到数据库）
     *
     * @param model 型号
     */
    public List<ComponentPrice> queryOne(String model, Map<String, BigDecimal> componentSupplierMap) {
        // 1. 入参校验
        if (Objects.isNull(model) || model.trim().isEmpty()) {
            log.warn("京北通宇单个查询：型号为空");
            return new ArrayList<>();
        }

        try {
            // 2. 接口调用限流
            callLimitService.supplierLimitCall(JBCHIP.getCode());

            // 3. 构建业务参数
            JSONObject bizContent = new JSONObject();
            bizContent.set("third_query_string", model.trim());

            // 4. 构建签名参数&生成签名
            JSONObject preSignParam = buildPreSignParam("jbchip.api.goods.third.fuzzy", "5901", bizContent);
            String sign = generateSign(preSignParam);

            // 5. 构建请求参数
            JSONObject requestParam = buildRequestParam(bizContent, "jbchip.api.goods.third.fuzzy", "5901", sign);

            // 6. 发送请求
            HttpResponse response = HttpRequest.post(API_URL)
                    .contentType("application/json;charset=" + CHARSET)
                    .body(requestParam.toString())
                    .timeout(TIMEOUT)
                    .execute();
            log.info("{} 京北通宇商城 queryOne API response: {}", model, response.body());
            // 7. 处理响应（同步库存）
            return handleQueryOneResponse(response, componentSupplierMap, model);

        } catch (Exception e) {
            log.error("京北通宇单个型号查询失败：model={}", model, e);
            MessageUtil.sentMessage("26827", "京北通宇单个型号queryOne查询失败" + e.getMessage(), "京北通宇单个型号查询失败");

        }
        return new ArrayList<>();
    }

    /**
     * 初始化数据同步（批量拉取供应商所有商品库存）
     * 范围：第201页到第448页，每页500条
     */
    public void init() {
        // 分页查询：201-448页
        for (int pageNo = 201; pageNo <= 448; pageNo++) {
            try {
                // 1. 构建业务参数
                JSONObject bizContent = new JSONObject();
                bizContent.set("page_no", pageNo);
                bizContent.set("page_size", 500);

                // 2. 构建签名参数&生成签名
                JSONObject preSignParam = buildPreSignParam("jbchip.api.goods.list", "5900", bizContent);
                String sign = generateSign(preSignParam);

                // 3. 构建请求参数
                JSONObject requestParam = buildRequestParam(bizContent, "jbchip.api.goods.list", "5900", sign);

                // 4. 发送请求
                HttpResponse response = HttpRequest.post(API_URL)
                        .contentType("application/json;charset=" + CHARSET)
                        .body(requestParam.toString())
                        .timeout(TIMEOUT)
                        .execute();

                // 5. 处理响应（同步库存）
                handleInitResponse(response, pageNo);

                // 6. 避免请求频率过高（可选：根据API限流策略调整）
                Thread.sleep(500);

            } catch (InterruptedException e) {
                log.error("京北通宇初始化数据：线程中断（pageNo={}）", pageNo, e);
                Thread.currentThread().interrupt(); // 恢复中断状态
                break;
            } catch (Exception e) {
                log.error("京北通宇初始化数据失败：pageNo={}", pageNo, e);
            }
        }
    }

    /**
     * 订单创建接口（向供应商发起订单请求）
     *
     * @param to 订单传输对象
     * @return 订单创建结果（含供应商订单号）
     */
    public CommonResult<String> order(OrderTo to) {
        // 1. 入参校验
        if (Objects.isNull(to) || CollectionUtils.isEmpty(to.getSkuList())) {
            log.warn("京北通宇创建订单：订单信息或SKU列表为空");
            return error(400, "型号列表为空");
        }

        try {
            // 2. 构建业务参数（订单信息）
            JSONObject bizContent = buildOrderBizContent(to);

            // 3. 构建签名参数&生成签名
            JSONObject preSignParam = buildPreSignParam("jbchip.api.order.create", "1530", bizContent);
            String sign = generateSign(preSignParam);

            // 4. 构建请求参数
            JSONObject requestParam = buildRequestParam(bizContent, "jbchip.api.order.create", "1530", sign);

            // 5. 发送请求
            HttpResponse response = HttpRequest.post(API_URL)
                    .contentType("application/json;charset=" + CHARSET)
                    .body(requestParam.toString())
                    .timeout(TIMEOUT)
                    .execute();

            // 6. 处理响应（返回供应商订单号）
            return handleOrderResponse(response);

        } catch (Exception e) {
            log.error("京北通宇创建订单失败：userOrderCode={}", to.getUserOrderCode(), e);
            return error(500, "订单创建失败：" + e.getMessage());
        }
    }

    // ------------------------------ 私有工具方法（封装通用逻辑） ------------------------------

    /**
     * 构建签名前的参数对象（包含所有参与签名的字段）
     *
     * @param method      API方法名
     * @param channelType 渠道类型
     * @param bizContent  业务参数
     * @return 签名前参数对象
     */
    private JSONObject buildPreSignParam(String method, String channelType, JSONObject bizContent) {
        JSONObject preSignParam = new JSONObject();
        preSignParam.set("charset", CHARSET);
        preSignParam.set("biz_content", bizContent.toString()); // 业务参数转JSON字符串
        preSignParam.set("partner_id", PARTNER_ID);
        preSignParam.set("method", method);
        preSignParam.set("time_stamp", DateUtil.now()); // 动态生成当前时间戳
        preSignParam.set("format", FORMAT);
        preSignParam.set("channel_type", channelType);
        preSignParam.set("app_id", APP_ID);
        preSignParam.set("version", VERSION);
        preSignParam.set("key", API_KEY); // 签名密钥（参与签名）
        return preSignParam;
    }

    /**
     * 生成签名（MD5加密 + Base64编码）
     *
     * @param preSignParam 签名前参数对象
     * @return 签名结果
     * @throws Exception JSON处理异常
     */
    private String generateSign(JSONObject preSignParam) throws Exception {
        // 1. 排序并拼接键值对（key=value&key=value）
        String sortedParamStr = sortAndJoinJsonKeyValues(preSignParam.toString());
        // 2. MD5加密（小写）
        String md5Str = MD5Util.md5(sortedParamStr).toLowerCase();
        // 3. Base64编码
        return Base64Util.encode(md5Str);
    }

    /**
     * 构建最终请求参数（包含签名字段）
     *
     * @param bizContent  业务参数
     * @param method      API方法名
     * @param channelType 渠道类型
     * @param sign        签名结果
     * @return 请求参数对象
     */
    private JSONObject buildRequestParam(JSONObject bizContent, String method, String channelType, String sign) {
        JSONObject requestParam = new JSONObject();
        requestParam.set("charset", CHARSET);
        requestParam.set("biz_content", bizContent.toString());
        requestParam.set("partner_id", PARTNER_ID);
        requestParam.set("method", method);
        requestParam.set("time_stamp", DateUtil.now());
        requestParam.set("format", FORMAT);
        requestParam.set("sign", sign); // 签名字段
        requestParam.set("channel_type", channelType);
        requestParam.set("app_id", APP_ID);
        requestParam.set("version", VERSION);
        requestParam.set("sign_type", SIGN_TYPE);
        return requestParam;
    }

    /**
     * 处理单个查询响应（同步库存数据）
     */
    private List<ComponentPrice> handleQueryOneResponse(HttpResponse response, Map<String, BigDecimal> componentSupplierMap, String model) {
        if (!response.isOk()) {
            log.error("京北通宇单个查询：HTTP请求失败，状态码={}，响应内容={}", response.getStatus(), response.body());
            MessageUtil.sentMessage("26827", "京北通宇单个型号handleQueryOneResponse查询失败" + response.body(), "京北通宇单个型号handleQueryOneResponse查询失败");
            return new ArrayList<>();
        }

        try {
            String responseBody = response.body();
            log.info("京北通宇单个查询API响应：{}", responseBody);
            JSONObject jsonResponse = JSONUtil.parseObj(responseBody);

            // 校验返回码
            int returnCode = jsonResponse.getInt("return_code", -1);
            if (returnCode != 1000) {
                String returnMsg = jsonResponse.getStr("return_msg", "未知错误");
                log.error("京北通宇单个查询API返回失败：returnCode={}，returnMsg={}", returnCode, returnMsg);
                return new ArrayList<>();
            }

            // 提取库存数据
            JSONObject returnData = jsonResponse.getJSONObject("return_data");
            if (Objects.isNull(returnData)) {
                log.warn("京北通宇单个查询：return_data为空");
                return new ArrayList<>();
            }

            JSONArray goodsList = returnData.getJSONArray("goods_list");
            List<ComponentPrice> componentPriceList = new ArrayList<>();
            String currency = returnData.getStr("currency", "RMB"); // 默认人民币
            for (int i = 0; i < goodsList.size(); i++) {
                JSONObject goods = goodsList.getJSONObject(i);
                ComponentStock stock = new ComponentStock(
                        null,  // 供应商无法提供picUrl
                        goods.getStr("part_no"),          // model
                        goods.getStr("category"),         // type
                        goods.getStr("brand_name"),       // brand
                        goods.getStr("description"),      // specifications
                        null,                             // attribute (无对应字段)
                        DEFAULT_STOCK_TYPE,               // stockType
                        JBCHIP.getCode(),                 // supplierCode
                        goods.getStr("goods_package")     // 包装信息
                );
                stock.setGoodsId(goods.getStr("goods_id"));
                stock.setPartnumber(goods.getStr("goods_id"));
                stock.setKeyword(model);
                stock.setUniqueId(SupplierCodeEnum.JBCHIP.getCode() + "_" + goods.getStr("goods_id"));
                JSONArray stepPrices = goods.getJSONArray("step_prices_map_list");
                handleStepPrices(stepPrices);
                componentStockService.saveComponentStockOfUniqueKey(stock);

                // 构建价格实体（去重：排除已存在的库存ID）
                ComponentPrice price = new ComponentPrice(
                        stock.getUniqueId(),
                        stepPrices.toString(),
                        goods.getLong("goods_number", 0L),
                        goods.getStr("goods_package"),
                        goods.getStr("pack"),
                        currency,
                        goods.getStr("part_no"), // 型号,
                        stepPrices.toString(),
                        salePriceConfigService.getSaleJson(stepPrices.toString(), goods.getStr("part_no"), currency),
                        componentSupplierMap.getOrDefault(JBCHIP.getCode(), BigDecimal.valueOf(2))
                );
                componentPriceService.createComponentPriceOfUniqueKey(price);
                price.setStockInfo(stock);
                componentPriceList.add(price);
            }
            return componentPriceList;

        } catch (Exception e) {
            log.error("京北通宇单个查询响应处理失败", e);
        }
        return new ArrayList<>();
    }

    /**
     * 处理初始化响应（批量同步库存数据）
     */
    private void handleInitResponse(HttpResponse response, int pageNo) {
        if (!response.isOk()) {
            log.error("京北通宇初始化数据：HTTP请求失败，pageNo={}，状态码={}", pageNo, response.getStatus());
            return;
        }

        try {
            String responseBody = response.body();
            JSONObject jsonResponse = JSONUtil.parseObj(responseBody);

            // 校验返回码
            int returnCode = jsonResponse.getInt("return_code", -1);
            if (returnCode != 1000) {
                String returnMsg = jsonResponse.getStr("return_msg", "未知错误");
                log.error("京北通宇初始化数据API失败：pageNo={}，returnCode={}，returnMsg={}",
                        pageNo, returnCode, returnMsg);
                return;
            }

            // 提取库存数据
            JSONObject returnData = jsonResponse.getJSONObject("return_data");
            if (Objects.isNull(returnData)) {
                log.warn("京北通宇初始化数据：pageNo={}，return_data为空", pageNo);
                return;
            }

            JSONArray goodsList = returnData.getJSONArray("goods_list");
            List<ComponentStock> stockList = new ArrayList<>();

            for (int i = 0; i < goodsList.size(); i++) {
                JSONObject goods = goodsList.getJSONObject(i);
                ComponentStock stock = new ComponentStock(
                        goods.getStr("goods_url"),    // picUrl
                        goods.getStr("part_no"),      // model
                        goods.getStr("category"),     // type
                        goods.getStr("brand_name"),   // brand
                        goods.getStr("description"),  // specifications
                        null,                         // attribute
                        DEFAULT_STOCK_TYPE,           // stockType
                        JBCHIP.getCode(),             // supplierCode
                        goods.getStr("goods_package") // 包装信息
                );
                stock.setGoodsId(goods.getStr("goods_id"));
                stockList.add(stock);
            }

            // 保存库存数据
            if (CollectionUtils.isNotEmpty(stockList)) {
                componentStockService.saveComponentStockBranch(stockList);
                log.info("京北通宇初始化数据：pageNo={}，成功同步{}条库存数据", pageNo, stockList.size());
            } else {
                log.info("京北通宇初始化数据：pageNo={}，无库存数据", pageNo);
            }

        } catch (Exception e) {
            log.error("京北通宇初始化数据响应处理失败：pageNo={}", pageNo, e);
        }
    }

    /**
     * 构建订单业务参数
     */
    private JSONObject buildOrderBizContent(OrderTo to) {
        JSONObject bizContent = new JSONObject();
        bizContent.set("out_order_no", to.getUserOrderCode());
        bizContent.set("third_buyer", to.getUserMark());
        bizContent.set("order_remark", to.getRemarks());
        bizContent.set("express_id", EXPRESS_ID);
        bizContent.set("is_direct", IS_DIRECT);

        // 构建商品列表
        List<Map<String, Object>> goodsList = new ArrayList<>();
        for (SKU sku : to.getSkuList()) {
            Map<String, Object> goodsMap = new HashMap<>(2);
            goodsMap.put("goods_id", sku.getGoodId());
            goodsMap.put("goods_count", sku.getNum());
            goodsList.add(goodsMap);
        }
        bizContent.set("goods_list", goodsList);

        return bizContent;
    }

    /**
     * 处理订单响应（返回供应商订单号）
     */
    private CommonResult<String> handleOrderResponse(HttpResponse response) {
        if (!response.isOk()) {
            log.error("京北通宇创建订单：HTTP请求失败，状态码={}，响应内容={}", response.getStatus(), response.body());
            return error(500, "HTTP请求失败：状态码=" + response.getStatus());
        }

        try {
            String responseBody = response.body();
            log.info("京北通宇创建订单API响应：{}", responseBody);
            JSONObject jsonResponse = JSONUtil.parseObj(responseBody);

            // 校验返回码
            int returnCode = jsonResponse.getInt("return_code", -1);
            if (returnCode != 1000) {
                String returnMsg = jsonResponse.getStr("return_msg", "未知错误");
                return error(500, "API请求失败：" + returnMsg);
            }

            // 提取订单号
            JSONObject returnData = jsonResponse.getJSONObject("return_data");
            if (Objects.isNull(returnData)) {
                return error(500, "API返回数据为空");
            }

            String jbchipOrderNo = returnData.getStr("jbchip_order_no");
            if (Objects.isNull(jbchipOrderNo)) {
                return error(500, "未获取到供应商订单号");
            }

            return success(jbchipOrderNo);

        } catch (Exception e) {
            log.error("京北通宇订单响应处理失败", e);
            return error(500, "订单响应处理失败：" + e.getMessage());
        }
    }

    /**
     * 处理阶梯价格（重命名字段）
     */
    private void handleStepPrices(JSONArray stepPrices) {
        if (Objects.isNull(stepPrices)) {
            return;
        }

        for (int i = 0; i < stepPrices.size(); i++) {
            JSONObject item = stepPrices.getJSONObject(i);
            // 替换字段名
            String price = item.getStr("goods_price");
            String quantity = item.getStr("goods_num");

            // 删除原有字段
            item.remove("goods_price");
            item.remove("goods_num");

            // 添加新的字段
            item.put("Price", price);
            item.put("Currency", "RMB");
            item.put("Quantity", quantity);
        }
    }

    /**
     * 对JSON参数按key排序并拼接为key=value&key=value格式
     * 用于生成签名
     */
    public static String sortAndJoinJsonKeyValues(String jsonString) throws Exception {
        com.fasterxml.jackson.databind.ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper();
        com.fasterxml.jackson.databind.JsonNode jsonNode = objectMapper.readTree(jsonString);

        List<String> keyValuePairs = new ArrayList<>();

        // 遍历JSON节点，构建键值对列表
        for (Map.Entry<String, com.fasterxml.jackson.databind.JsonNode> entry :
                (Iterable<Map.Entry<String, com.fasterxml.jackson.databind.JsonNode>>) () -> jsonNode.fields()) {
            String key = entry.getKey();
            String value = entry.getValue().isTextual() ?
                    entry.getValue().asText() : entry.getValue().toString();
            keyValuePairs.add(key + "=" + value);
        }

        // 对键值对进行排序
        Collections.sort(keyValuePairs);

        // 用"&"连接所有键值对
        return String.join("&", keyValuePairs);
    }
}
